package com.itlong.cloud.intercept.sdkV2;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.RateLimiter;
import com.itlong.cloud.POJO.PO.PropertyUserInfoPO;
import com.itlong.cloud.POJO.VO.MessageVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.enumerate.ecode.SDKErrorCodeEnum;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.user.sdk.ICloudTalkSDKAppUserServiceClient;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

/**
 * <desc>
 * SDK限流拦截器
 * </desc>
 *
 * @createDate 2019/10/08
 */
@Aspect
@Component
@Order(0)
public class SDKRateLimitInterceptor {
    private static Logger LOG = LoggerFactory.getLogger(SDKRateLimitInterceptor.class);

    //qps限流数量
    @Value("${" + PlatformConstants.SDK_QPS_LIMIT + "}")
    private double SDK_QPS_LIMIT;

    //token限流数量
    @Value("${" + PlatformConstants.SDK_TOKEN_QPS_LIMIT + "}")
    private double SDK_TOKEN_QPS_LIMIT;

    private RateLimiter rateLimiter;

    @Autowired
    RedisService redisService;

    @Autowired
    ICloudTalkSDKAppUserServiceClient iCloudTalkSDKAppUserServiceClient;

    //令牌桶缓存
    private LoadingCache<String, RateLimiter> caches = CacheBuilder.newBuilder()
            .maximumSize(1000)
            .expireAfterWrite(1, TimeUnit.DAYS)
            .build(new CacheLoader<String, RateLimiter>() {
                @Override
                public RateLimiter load(String key) throws Exception {
                    // 新的token初始化
                    return RateLimiter.create(SDK_TOKEN_QPS_LIMIT);
                }
            });

    // 定义一个切入点
    @Pointcut("execution(* com.itlong.cloud.controller.sdkV2..*.*(..)) && !@annotation(com.itlong.cloud.annotation.UnAuthAccessRequired)")
    public void excudeService() {
    }

    /**
     * <desc>
     * SDK限流拦截器
     * </desc>
     *
     * @param
     * @author Qiang.S
     * @createDate 2019/10/08
     */
//    @Around("excudeService()")
    public Object twiceAsOld(ProceedingJoinPoint thisJoinPoint) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getParameter("token");

        if (StringUtils.isNotBlank(token)) {
            PropertyUserInfoPO propertyUserInfoPO = iCloudTalkSDKAppUserServiceClient.developerRetrieve(token);
            if (propertyUserInfoPO != null) {
                rateLimiter = caches.get(token);//单应用使用缓存ratelimiter进行限流
            }
        }
        if (rateLimiter == null) {
            rateLimiter = RateLimiter.create(SDK_QPS_LIMIT);
        }
        boolean flag = rateLimiter.tryAcquire(0, TimeUnit.MILLISECONDS);
        if (flag) {
            return thisJoinPoint.proceed();
        }else {
            return new MessageVO(SDKErrorCodeEnum.SDK_RATE_LIMIT_ERR.getErrorCode());
        }

        //分布式使用redis方式限流
//        Jedis redis = new Jedis("127.0.0.1", 6379);
//        String fileName = this.getClass().getClassLoader().getResource("rateLimit.lua").getPath();
//        String luaScript = Files.toString(new File(fileName), Charset.defaultCharset());
//        redis.eval(luaScript, Lists.newArrayList(token), Lists.newArrayList(SDK_TOKEN_QPS_LIMIT+""));//判断是否限流
    }
}
